package com.psq.base.user.manager

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.dataStore
import androidx.lifecycle.asLiveData
import com.psq.base.user.UserPreferences
import com.psq.base.user.datastore.UserPreferencesSerializer
import com.psq.core.common.CommonAppContext
import com.psq.base.user.model.LoginState
import com.psq.base.user.model.User
import com.psq.base.user.repository.UserPreferencesRepository
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

// Build the DataStore
private const val DATA_STORE_FILE_NAME = "user_prefs.pb"
private val Context.userPreferencesStore: DataStore<UserPreferences> by dataStore(
    fileName = DATA_STORE_FILE_NAME,
    serializer = UserPreferencesSerializer
)

class UserManager private constructor(context: Context) {

    companion object {
        private var isReset = false

        @Volatile
        private var INSTANCE: UserManager? = null

        fun getInstance(context: Context = CommonAppContext.getInstance()): UserManager {
            return INSTANCE ?: synchronized(this) {
                INSTANCE?.let {
                    return it
                }
                val instance = UserManager(context)
                INSTANCE = instance
                INSTANCE?.resetLoginType()
                instance
            }
        }
    }

    private val coroutineScope by lazy { CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) }

    private val _loginStateFlow = MutableStateFlow<LoginState>(LoginState.Logout)
    val loginStateFlow: StateFlow<LoginState> = _loginStateFlow

    private val userPreferencesRepository by lazy {
        UserPreferencesRepository(context.userPreferencesStore)
    }
    val userPreferencesFlow = userPreferencesRepository.userPreferencesFlow

    data class UserUiModel(val state: LoginState, val userPreferences: UserPreferences)

    private val userUiFlow: Flow<UserUiModel> = combine(
        loginStateFlow,
        userPreferencesFlow
    ) { state: LoginState, userPreferences: UserPreferences ->
        UserUiModel(state, userPreferences)
    }

    val userUiModelLiveData = userUiFlow.asLiveData()

    // 更新登录状态
    fun updateLoginState(state: LoginState) {
        coroutineScope.launch {
            runCatching {
                _loginStateFlow.emit(state)
            }
        }
    }

    // 差量更新用户信息
    fun updateUserPreferences(apply: UserPreferences.Builder.() -> UserPreferences.Builder) {
        coroutineScope.launch {
            userPreferencesRepository.updateUserPreferences(apply)
        }
    }

    // 全量更新用户信息
    @Suppress("USELESS_ELVIS")
    fun updateUserPreferences(user: User) {
        coroutineScope.launch {
            userPreferencesRepository.updateUserPreferences {
                userId = user.userId ?: -1
                userName = user.userName ?: ""
                mobile = user.mobile ?: ""
                token = user.token ?: ""
                this
            }
        }
    }

    /**
     * 打开app，恢复登录状态
     */
    fun resetLoginType() {
        if (isReset) {
            return
        }
        isReset = true
        coroutineScope.launch {
            val token = userPreferencesFlow.stateIn(coroutineScope).value.token
            if (token != null && token != "") {
                updateLoginState(LoginState.Login)
            }
        }

    }

    fun clearUserPreferences() {
        coroutineScope.launch {
            userPreferencesRepository.updateUserPreferences {
                clear()
            }
        }
    }

    fun login(user: User) {
        updateLoginState(LoginState.Login)
        updateUserPreferences(user)
    }

    fun logout() {
        updateLoginState(LoginState.Logout)
        clearUserPreferences()
    }

}